from random import randint
from sklearn.cluster import KMeans
import pandas as pd
import json
from rest_framework import status
from rest_framework.parsers import JSONParser
from .serializer import JsonFileSerializer
from Utils.Constant import SCHOOL_DEGREE
import base64

from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from Apps.Data.models import JobModel, JobCal
from Apps.Data.serializer import JobModelSerializer
from Utils.Constant import RESULT


# Create your views here.
# 返回岗位语言分布
@api_view(['GET'])
def get_language_count(request):
    job_list = JobModel.objects.all()
    dist = {}

    for job in job_list:
        language = job.language
        if language not in dist:
            dist[language] = 1
        else:
            dist[language] += 1

    countList, langList = [], []
    for (lang, number) in dist.items():
        countList.append(number)
        langList.append(lang)

    return Response({'status': RESULT['success'], 'CountList': countList, 'LangList': langList})


# 返回岗位学历分布
@api_view(['GET'])
def get_school_count(request):
    job_list = JobModel.objects.all()
    dist = {}
    for job in job_list:
        shcool = job.job_degree
        if shcool not in dist:
            dist[shcool] = 1
        else:
            dist[shcool] += 1
    return Response({'status': RESULT['success'], 'data': dist})


# 返回每个城市对应岗位数量
@api_view(['GET'])
def get_city_count(request):
    job_list = JobModel.objects.all()
    dist = {}
    for job in job_list:
        city = job.city_name
        if city not in dist:
            dist[city] = 1
        else:
            dist[city] += 1

    return Response({'status': RESULT['success'], 'data': dist})


# 返回岗位相关技术词云
@api_view(['GET'])
def get_skill_wordcloud(request):
    # TODO  实现路径适配
    # with open('C:\\Users\\17914\\job_viewer_backend\\dataStore\\hh.png', 'rb') as img:
    with open('/Users/hnitro/Desktop/job_viewer_backend/dataStore/hh.png', 'rb') as img:

        img_data = base64.b64encode(img.read()).decode('utf-8')
    return Response({'status': RESULT['success'], 'data': img_data})


# 获取主页 岗位数，城市数，平均工资
@api_view(['GET'])
def get_banner_data(request):
    job_list = JobModel.objects.all()
    city_set = {}

    # 计算城市数
    for job in job_list:
        if job.city_name not in city_set:
            city_set[job.city_name] = 1

    # 计算平均工资
    from django.db.models import Avg
    average_value = JobCal.objects.aggregate(
        average=Avg('average_salary'))['average']

    return Response({
        'status': RESULT['success'],
        'data': {
            'count': len(job_list),
            'average': round(average_value, 2),  # 保留两位小数
            'city_count': len(city_set)
        }
    })


# 获取数据库后7条数据，用于滚动展示
@api_view(['GET'])
def get_scroll_data(request):
    job_list = JobModel.objects.all()
    sliceData = JobModel.objects.order_by(
        '-id')[:7]    # django ORM不支持负下标切片，所以先反排序，切正下标
    return Response({'status': RESULT['success'], 'data': JobModelSerializer(sliceData, many=True).data})


# 实现文件上传 （多条数据录入）


@api_view(['POST'])
def post_json_file(request):
    print(request.FILES)

    serializer = JsonFileSerializer(data=request.data)

    if serializer.is_valid():
        instance = serializer.save()
        # 读取上传的JSON文件并解析

        # TODO 实现数据插入
        json_data = instance.file.read().decode('utf-8')
        next_data = json.loads(json_data)

        for file_item in next_data:
            jobModel = JobModel()
            jobModel.set_fields(file_item['brand_name'],
                                file_item['job_name'], file_item['scope'],
                                file_item['salary_desc'], file_item['stage'], file_item['welfare'],
                                file_item['city_name'], file_item['area_district'], file_item['skills'],
                                file_item['job_exp'], file_item['job_degree'], "手动-多批量上传", file_item['lang'])
            jobModel.save()

        return Response(serializer.data)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


#  获取 职位推荐表单数据回显
@api_view(['GET'])
def get_recommend_dict(request):
    jobList = JobModel.objects.all()
    languageCategory, cityCategory = {}, {}

    for job in jobList:
        city = job.city_name
        lang = job.language

        if city not in cityCategory:
            cityCategory[city] = True
        if lang not in languageCategory:
            languageCategory[lang] = True

    return Response({'status': RESULT['success'],
                    'data': {
                        'langList': [x for x in languageCategory],
                        'cityList': [x for x in cityCategory]
    }
    })


# 薪资正则化
def normalize_salary(maxValue, minValue, salary):

    prefix, subfix = salary.split('-')
    iprefix = int(prefix.strip('k').strip('K'))
    isubfix = int(subfix.strip('k').strip('K'))

    # 最小正则化
    ans = float(iprefix - minValue) / float(maxValue - minValue)
    return ans  # 返回正则薪资


# 正则化城市|编程语言


def normalize_city_and_lang(flag, input):
    # 硬编码列表
    city_hash = {'武汉': 0, '北京': 1, '广州': 2, '杭州': 3, '上海': 4, '深圳': 5}
    lang_hash = {'py': 0, 'c#': 1, 'cpp': 2,
                 'go': 3, 'java': 4, 'php':  5, 'fronted': 6, 'c': 1}
    if flag == 'city':
        return city_hash[input]
    else:
        return lang_hash[input]


# 推荐 职位


@api_view(['GET'])
def recommend_job_by_kmeans(request):

    # 使用K-means聚类推荐相关职位
    jobList = JobModel.objects.all()
    jobListFilter = []
    # 注意，这里的矩阵每一个是float  ---> xyz的三维聚类
    # 所以需要去正则化薪资,城市,语言

    maxValue, minValue = 0, 0x3f3f3f3f
    for job in jobList:
        if job.salary_desc.find('薪') != -1:
            continue
        prefix, subfix = job.salary_desc.split('-')
        iprefix = int(prefix.strip('k').strip('K'))
        isubfix = int(subfix.strip('k').strip('K'))

        # print(iprefix, isubfix)
        maxValue = max(maxValue, isubfix)
        minValue = min(minValue, iprefix)

    # 构造用户趋向矩阵
    user_input = {
        'language': request.GET.get('lang'),
        'city': request.GET.get('city'),
        'salary': request.GET.get('salary_desc')  # 默认7-10k
    }
    print(user_input)

    if user_input['language'] == '':
        user_input['language'] = randint(0, 5)
    else:
        user_input['language'] = normalize_city_and_lang(
            'lang', user_input['language'])

    if user_input['city'] == '':
        user_input['city'] = randint(0, 6)
    else:
        user_input['city'] = normalize_city_and_lang(
            'city', user_input['city'])

    if user_input['salary'] == '':
        user_input['salary'] = 0.066667
    else:
        user_input['salary'] = normalize_salary(
            minValue, maxValue, user_input['salary'])

    print(user_input)

    normal_salary = []
    normal_city = []
    normal_lang = []
    print(f"{minValue} - {maxValue}")
    for job in jobList:
        if job.salary_desc.find('薪') != -1:
            continue
        else:
            normal_salary.append(normalize_salary(
                maxValue, minValue, job.salary_desc))
            normal_city.append(normalize_city_and_lang('city', job.city_name))
            normal_lang.append(normalize_city_and_lang('lang', job.language))
            jobListFilter.append(job)
    job_data = pd.DataFrame({
        'language': normal_lang,
        'city': normal_city,
        'salary': normal_salary
    })

    hash_row = {}
    # 将矩阵的每一列哈希对应的JobModel
    for index, row in job_data.iterrows():
        line = str(index) + '-'.join(str(x)for x in row)   # 很蠢的index标记，使得哈希不重复
        hash_row[line] = jobListFilter[index]

    kmeans = KMeans(n_clusters=6)  # 假设有12个聚类中心  6/7/12 12是综合考虑城市+语言得到的
    kmeans.fit(job_data[['language', 'city', 'salary']])

    user_vector = pd.DataFrame(user_input, index=[0])

    user_cluster = kmeans.predict(
        user_vector[['language', 'city', 'salary']])
    recommended_jobs = job_data[kmeans.labels_ == user_cluster[0]]

    print(recommended_jobs.head(1000))  # Kmeans不是监督学习，综合三个特征考虑，所以会出现不对应的情况
    top5 = recommended_jobs.head(3000)
    ansList = []
    # ansList = [hash_row[job] for job in recommended_jobs]
    for index, row in top5.iterrows():
        line = str(index) + '-'.join(str(x) for x in row)
        if normalize_city_and_lang('city', hash_row[line].city_name) != user_input['city'] or normalize_city_and_lang('lang', hash_row[line].language) != user_input['language']:
            continue

        # print(hash_row[line])
        if len(ansList) > 30:
            break
        ansList.append(hash_row[line])
        # TODO  cpp职位数据标注有问题
    return Response({'data': JobModelSerializer(ansList, many=True).data})
